package com.baseframe.auth.granter;



import com.baseframe.tool.utils.redis.CommonRedisUtil;
import com.baseframe.tool.utils.web.WebUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

import static com.baseframe.auth.constant.BaseAuthConstant.*;


/**
 * 图形验证码登录
 * 基于验证码的OAuth2令牌授权
 */
@Slf4j
public class BaseCaptchaTokenGranter extends AbstractTokenGranter {

    private static final String GRANT_TYPE = "captcha";
    private final AuthenticationManager authenticationManager;

    public BaseCaptchaTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.authenticationManager = authenticationManager;
    }

    //认证逻辑
    @Override
    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {

        //客户端信息
        //获取用户名和密码
        Map<String, String> parameters = tokenRequest.getRequestParameters();
        String username = parameters.get(USERNAME);
        String password = parameters.get(PASSWORD);
        //获取验证码
        HttpServletRequest request = WebUtil.getRequest();
        String key = CAPTCHA_REDIS_KEY+ request.getHeader(CAPTCHA_KEY);
        String code = request.getHeader(CAPTCHA_CODE);
        String redisCode = CommonRedisUtil.getValue(key);
        //删除验证码防止被复用
        CommonRedisUtil.delete(key);
        if (redisCode==null||code==null){
            log.error("headerCode:{}\nredisCode:{}",code,redisCode);
            throw new UserDeniedAuthorizationException("验证码已过期~");
        }
        if (!code.equalsIgnoreCase(redisCode)){
            throw new UserDeniedAuthorizationException("验证码错误~");
        }
        //
        Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password);
        ((AbstractAuthenticationToken) userAuth).setDetails(parameters);

        try {
            userAuth = authenticationManager.authenticate(userAuth);
        }catch (Exception e){
            throw new UserDeniedAuthorizationException(e.getMessage());
        }
        if (userAuth == null || !userAuth.isAuthenticated()) {
            throw new UserDeniedAuthorizationException("无法对用户进行身份验证: " + username);
        }


        OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
        return new OAuth2Authentication(storedOAuth2Request, userAuth);
    }
}
